package org.jawa.database;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.jawa.ApplicationState;
import org.jawa.Constants;

/*
 * 默认程序提供DBCP的数据库连接池
 */
public class DefaultConnectionProvider implements ConnectionProvider {

	protected static final Object initLock = new Object();
	private DataSource dataSource;
	private BasicDataSource ds;

	private String driver;
	public String getDriver() {
		return driver;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	public String getServerURL() {
		return serverURL;
	}

	public void setServerURL(String serverURL) {
		this.serverURL = serverURL;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getMinConnections() {
		return minConnections;
	}

	public void setMinConnections(int minConnections) {
		this.minConnections = minConnections;
	}

	public int getMaxConnections() {
		return maxConnections;
	}

	public void setMaxConnections(int maxConnections) {
		this.maxConnections = maxConnections;
	}

	public double getConnectionTimeout() {
		return connectionTimeout;
	}

	public void setConnectionTimeout(double connectionTimeout) {
		this.connectionTimeout = connectionTimeout;
	}

	public boolean isMysqlUseUnicode() {
		return mysqlUseUnicode;
	}

	public void setMysqlUseUnicode(boolean mysqlUseUnicode) {
		this.mysqlUseUnicode = mysqlUseUnicode;
	}

	private String serverURL;
	private String username;
	private String password;
	private int minConnections;
	private int maxConnections;
	private double connectionTimeout;
	private boolean mysqlUseUnicode;
	public static final String DB_DEFAULT_PROVIDER_DRIVER = "database.defaultProvider.driver";
	public static final String DB_DEFAULT_PROVIDER_SERVER_URL = "database.defaultProvider.serverURL";
	public static final String DB_DEFAULT_PROVIDER_USERNAME = "database.defaultProvider.username";
	public static final String DB_DEFAULT_PROVIDER_PASSWORD = "database.defaultProvider.password";
	public static final String DB_DEFAULT_PROVIDER_MIN_CONNECTION = "database.defaultProvider.minConnections";
	public static final String DB_DEFAULT_PROVIDER_MAX_CONNECTIONS = "database.defaultProvider.maxConnections";
	public static final String DB_DEFAULT_PROVIDER_TIMEOUT = "database.defaultProvider.connectionTimeout";

	public DefaultConnectionProvider() {
		dataSource = new JawaDataSource(this);
		minConnections = 3;
		maxConnections = 25;
		connectionTimeout = 0.5D;
		loadProperties();
	}

	/**
	 * 读取数据库默认的连接池配置
	 */
	private void loadProperties() {
		driver = Constants
				.getXMLProperty("database.defaultProvider.driverClassName");
		serverURL = Constants
				.getXMLProperty("database.defaultProvider.serverURL");
		username = Constants
				.getXMLProperty("database.defaultProvider.username");
		password = Constants
				.getXMLProperty("database.defaultProvider.password");
		String minCons = Constants
				.getXMLProperty("database.defaultProvider.minConnections");
		String maxCons = Constants
				.getXMLProperty("database.defaultProvider.maxConnections");
		String conTimeout = Constants
				.getXMLProperty("database.defaultProvider.connectionTimeout");

		// See if we should use Unicode under MySQL
		mysqlUseUnicode = Constants.getXMLProperty("database.mysql.useUnicode",
				false);
		try {
			if (minCons != null) {
				minConnections = Integer.parseInt(minCons);
			}
			if (maxCons != null) {
				maxConnections = Integer.parseInt(maxCons);
			}
			if (conTimeout != null) {
				connectionTimeout = Double.parseDouble(conTimeout);
			}
		} catch (Exception e) {
			// Log.error("Error: could not parse default pool properties. " +
			// "Make sure the values exist and are correct.", e);
		}
	}

	/**
	 * 保存数据库默认的连接池配置
	 */
	private void saveProperties() {
		Constants.setXMLProperty("database.defaultProvider.driverClassName",
				driver);
		Constants.setXMLProperty("database.defaultProvider.serverURL",
				serverURL);
		Constants.setXMLProperty("database.defaultProvider.username", username);
		Constants.setXMLProperty("database.defaultProvider.password", password);
		Constants.setXMLProperty("database.defaultProvider.minConnections",
				Integer.toString(minConnections));
		Constants.setXMLProperty("database.defaultProvider.maxConnections",
				Integer.toString(maxConnections));
		Constants.setXMLProperty("database.defaultProvider.connectionTimeout",
				Double.toString(connectionTimeout));
	}

	@Override
	public Connection getConnection() throws SQLException {
		Connection conn = null;
		try {
			conn = ds.getConnection();
		} finally {
		}
		return conn;
	}

	@Override
	public boolean isPooled() {
		return false;
	}

	@Override
	public void destroy() {
		synchronized (initLock) {
			if (ds != null)
				try {
					ds.close();
				} catch (Exception e) {
				}
			ds = null;
		}
	}

	@Override
	public void restart() {
		destroy();
		loadProperties();
		start();
	}

	@Override
	public void start() {
		if (driver == null
				&& ApplicationState.RUNNING == Constants.getApplicationState()) {
			// log.severe(
			// "Connection Pool cannot be started : no driver was found");
			return;
		}
		if (driver == null)
			return;
		synchronized (initLock) {
			try {
				// connectionPool = new ConnectionPool(driver, serverURL,
				// username, password, minConnections, maxConnections,
				// connectionTimeout);
				// 启动DBCP的连接池
				Properties dbcpProperties = new Properties();
				dbcpProperties.put("driverClassName", driver);
				dbcpProperties.put("url", serverURL);
				dbcpProperties.put("username", username);
				dbcpProperties.put("password", password);
				// Pool size
				dbcpProperties.put("maxActive", minConnections);

				dbcpProperties.put("poolPreparedStatements", String
						.valueOf(Boolean.TRUE));
				dbcpProperties.put("maxOpenPreparedStatements", maxConnections);
				dbcpProperties.put("defaultAutoCommit", true);

				ds = (BasicDataSource) BasicDataSourceFactory
						.createDataSource(dbcpProperties);
				Connection conn = ds.getConnection();
				conn.close();
			} catch (Exception e) {
				// log.log(Level.SEVERE, e.getMessage(), e);
				e.printStackTrace();
			}
		}
	}

	@Override
	public DataSource getDataSource() {
		return dataSource;
	}

}
